package com.zz.server.handle.defaults;

import com.zz.common.annotation.Executor;
import com.zz.common.config.Constants;
import com.zz.common.datasource.DataSource;
import com.zz.common.datasource.DataSourceFactory;
import com.zz.common.entity.Information;
import com.zz.common.entity.Meta;
import com.zz.common.entity.ProtocolInfo;
import com.zz.common.enums.MessageType;
import com.zz.common.enums.SerializationType;
import com.zz.common.handle.executor.AbstractMessageExecutor;
import com.zz.common.protocol.DefaultProtocol;
import com.zz.common.utils.ObjectUtil;
import com.zz.common.utils.SnowflakeUtil;
import com.zz.server.config.ChannelCache;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * 客户端初始化连接成功，触发客户端事件执行pipeline中缓存的消息
 *
 * @author zz
 */
@Slf4j
@Executor(msgType = MessageType.TYPE_CONNECT)
public class ConnectExecutor extends AbstractMessageExecutor {

    private final DataSource dataSource = DataSourceFactory.getTunnelSource();
    @Override
    public void execute(Information information) {
        DefaultProtocol protocol = (DefaultProtocol) information.getProtocolMsg();
        ChannelHandlerContext context = information.getContext();
        Meta meta = protocol.getMeta();
        if (ObjectUtil.isNull(meta.getConfig()) || ObjectUtil.isEmptys(meta.getConfig().getDomain())) {
            log.error("client connect error, config is null");
            return;
        }
        // 获取当前客户端主通道
        Channel masterChannel = ChannelCache.getChannelByDomain(meta.getConfig().getDomain());
        if (ObjectUtil.isNull(masterChannel) || !masterChannel.isActive()) {
            log.error("client connect error, masterChannel is null");
            return;
        }
        // 获取当前客户端本地通道
        Map<String, Channel> channelCache = masterChannel.attr(Constants.Attributes.CHANNEL_CACHE).get();
        if (ObjectUtil.isNull(channelCache) || channelCache.isEmpty() || !channelCache.containsKey(meta.getLocalChannelId())) {
            log.error("client connect error, localChannel is null");
            return;
        }
        Channel localChannel = channelCache.get(meta.getLocalChannelId());
        if (ObjectUtil.isNull(localChannel) || !localChannel.isActive()) {
            log.error("client connect error, localChannel is null");
            return;
        }
        // 将该salveServerChannel 与 clientChannel 重新绑定绑定
        localChannel.attr(Constants.Attributes.SERVER_CHANNEL).set(context.channel());
        context.channel().attr(Constants.Attributes.LOCAL_CHANNEL).set(localChannel);
        // 触发客户端连接成功事件
        localChannel.pipeline().fireUserEventTriggered(meta.getConfig().getProxyType());
    }

    @Override
    public void execute(ProtocolInfo protocolInfo) {
        Channel serverChannel = protocolInfo.getServerChannel();
        // 构建连接消息
        DefaultProtocol protocolMsg = DefaultProtocol.builder().type(MessageType.TYPE_CONNECT)
                .serialNumber(SnowflakeUtil.genSnowflakeId())
                .serializationType(SerializationType.PROTOSTUFF)
                .data(protocolInfo.getData())
                .meta(Meta.builder().clientId(protocolInfo.getClientId())
                        .localChannelId(protocolInfo.getContext().channel().id().asLongText())
                        .serverChannelId(serverChannel.id().asLongText())
                        .config(dataSource.getClientConfigIdByDomain(protocolInfo.getDomain())).build())
                .build();

        serverChannel.writeAndFlush(protocolMsg);
    }
}
